package org.mozhu.mboot.core.json.jackson;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.mozhu.mboot.core.json.JSONDeserializer;
import org.mozhu.mboot.core.json.JSONHandlerProvider;
import org.mozhu.mboot.core.json.JSONParseException;
import org.mozhu.mboot.core.json.JSONSerializer;

import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.lang.reflect.Type;

public class JSONHandlerJacksonProvider implements JSONHandlerProvider {

    private JSONDeserializer jsonDeserializer;

    private JSONSerializer jsonSerializer;

    public JSONHandlerJacksonProvider(JacksonObjectMapperConfigurer objectMapperConfigurer) {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapperConfigurer.configure(objectMapper);
        jsonDeserializer = new JacksonJSONDeserializer(objectMapper);
        jsonSerializer = new JacksonJSONSerializer(objectMapper);
    }

    @Override
    public JSONDeserializer getJSONDeserializer() {
        return this.jsonDeserializer;
    }

    @Override
    public JSONSerializer getJSONSerializer() {
        return this.jsonSerializer;
    }

    class JacksonJSONDeserializer implements JSONDeserializer {

        private ObjectMapper objectMapper;

        public JacksonJSONDeserializer(ObjectMapper objectMapper) {
            this.objectMapper = objectMapper;
        }

        @Override
        public Object deserialize(Reader reader) throws JSONParseException, IOException {
            return objectMapper.readValue(reader, Object.class);
        }

        @Override
        public <T> T deserialize(Reader reader, Class<T> valueType) throws JSONParseException, IOException {
            return objectMapper.readValue(reader, valueType);
        }

        @Override
        public <T> T deserialize(Reader reader, Type valueType) throws JSONParseException, IOException {
            return objectMapper.readValue(reader, objectMapper.constructType(valueType));
        }
    }

    class JacksonJSONSerializer implements JSONSerializer {

        private ObjectMapper objectMapper;

        public JacksonJSONSerializer(ObjectMapper objectMapper) {
            this.objectMapper = objectMapper;
        }

        @Override
        public void serialize(Writer writer, Object object) throws IOException {
            objectMapper.writeValue(writer, object);
        }

        @Override
        public void serializePretty(Writer writer, Object object) throws IOException {
            objectMapper.writerWithDefaultPrettyPrinter().writeValue(writer, object);
        }

        @Override
        public String toJSONString(Object object) throws IOException {
            return objectMapper.writeValueAsString(object);
        }

        @Override
        public String toPrettyJSONString(Object object) throws IOException {
            return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(object);
        }

    }

}
